home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*______________________________________________________________________
- |
- | IvtoGl.c - convert inventor object to gl object
- |
- | this does not accept general inventor files, and you shouldn't feed
- | it just any file. The limitations are very strict. The two most
- | restrictive are only support for objects that are indexed per vertex,
- | and it doesn't follow the inventor structure.
- |
- | (c) 1994 frans van hoesel, Xtreme Graphics Software
- |
- */
-
- #include <ctype.h>
- #include <search.h>
- #include <string.h>
- #include <stdio.h>
- #include <gl/gl.h>
- #include <malloc.h>
- #include "io.h"
- #include "IvtoGL.h"
- #include "blixvect.h"
-
- #define NUM_KEYWORDS 23
- #define MAXELEM 2000
- #define MAXEMIS 25 /* used only in fire */
-
- Object build_object(int mat, int num, float vec[MAXELEM][3],
- float punt[MAXELEM][3], int nin[MAXELEM], int cin[MAXELEM],
- int ein[MAXELEM], float emis[MAXEMIS][3], int ecnt, int backmode);
- void smooth_normals(int cnt, float vec[MAXELEM][3], int nin[MAXELEM],
- int cin[MAXELEM]) ;
- int matcmp(const void *a, const void *b) ;
-
- static int last_mat_used;
- static int current_backmode;
-
-
- /*________________________________________________________________________
- |
- | read_object_file - reads the specified inventor file
- |
- */
-
- void read_object_file(const char *filename, int obj) {
- ENTRY item, *found_item;
- /* name to look for in table */
-
- int i = 0;
- int j;
- int objcnt = 0;
- static int done;
- static Object objects[100];
- static float default_mat[21] = {
- ALPHA, 0.0,
- AMBIENT, 0.1, 0.1, 0.1,
- DIFFUSE, 0.4, 0.4, 0.4,
- EMISSION, 0.0, 0.0, 0.0,
- SPECULAR, 0.0, 0.0, 0.0,
- SHININESS, 0.0,
- LMNULL
- };
- static float current_mat[21];
- static float this_mat[21];
- float this_vec[MAXELEM][3];
- float this_pnt[MAXELEM][3];
- float this_trans[3];
- float this_scale[3];
- int this_axis[3];
- int this_rot;
- float this_angle[3];
- float this_crease;
- int this_cin[MAXELEM];
- int this_nin[MAXELEM];
- int this_ein[MAXELEM];
- float this_emis[MAXEMIS][3];
- static int vcnt, pcnt, ccnt, ncnt, ecnt, eicnt;
- static char *s;
- static int object_is_open;
- static int mat;
- static int backface_mode;
-
-
- /* create table, it's a bit silly that I do this every time, but
- * this routine is only called a few times
- */
- hcreate(NUM_KEYWORDS);
- item.key = "ambientColor"; item.data = (char *) 1; hsearch(item, ENTER);
- item.key = "diffuseColor"; item.data = (char *) 2; hsearch(item, ENTER);
- item.key = "specularColor"; item.data = (char *) 3; hsearch(item, ENTER);
- item.key = "emissiveColor"; item.data = (char *) 4; hsearch(item, ENTER);
- item.key = "shininess"; item.data = (char *) 5; hsearch(item, ENTER);
- item.key = "transparency"; item.data = (char *) 6; hsearch(item, ENTER);
- item.key = "vector"; item.data = (char *) 7; hsearch(item, ENTER);
- item.key = "coordIndex"; item.data = (char *) 8; hsearch(item, ENTER);
- item.key = "normalIndex"; item.data = (char *) 9; hsearch(item, ENTER);
- item.key = "point"; item.data = (char *)10; hsearch(item, ENTER);
- item.key = "end"; item.data = (char *)11; hsearch(item, ENTER);
- item.key = "Separator"; item.data = (char *)12; hsearch(item, ENTER);
- item.key = "hints"; item.data = (char *)13; hsearch(item, ENTER);
- item.key = "translation"; item.data = (char *)14; hsearch(item, ENTER);
- item.key = "axis"; item.data = (char *)15; hsearch(item, ENTER);
- item.key = "angle"; item.data = (char *)16; hsearch(item, ENTER);
- item.key = "scaleFactor"; item.data = (char *)17; hsearch(item, ENTER);
- item.key = "creaseAngle"; item.data = (char *)18; hsearch(item, ENTER);
- item.key = "materialIndex"; item.data = (char *)19; hsearch(item, ENTER);
- last_mat_used = -2;
- current_backmode = TRUE;
- backface_mode = TRUE;
- vzero(this_trans);
- vset(this_scale, 1, 1, 1);
- this_axis[0] = 'X';
- this_axis[1] = 'X';
- this_axis[2] = 'X';
- this_angle[0] = 0;
- this_angle[1] = 0;
- this_angle[2] = 0;
- this_crease = 2.0;
- this_rot = 0;
- open_file(filename);
- for (i=0; i< 21; i++) {
- this_mat[i] = default_mat[i];
- current_mat[i] = default_mat[i];
- }
- done = FALSE;
- object_is_open = FALSE;
- do {
- s = accept_str();
- if (!(isalpha(*s))) {
- skip_line();
- continue;
- }
- item.key = s;
- found_item = hsearch(item, FIND);
- if (found_item == NULL)
- continue;
- switch((int) found_item->data) {
- case 1: /* ambientColor */
- this_mat[3] = accept_float();
- this_mat[4] = accept_float();
- this_mat[5] = accept_float();
- if (read_ch('~') == 0) {
- this_mat[3] = 0.2;
- this_mat[4] = 0.2;
- this_mat[5] = 0.2;
- }
- break;
- case 2: /* diffuseColor */
- this_mat[7] = accept_float();
- this_mat[8] = accept_float();
- this_mat[9] = accept_float();
- if (read_ch('~') == 0) {
- this_mat[7] = 0.8;
- this_mat[8] = 0.8;
- this_mat[9] = 0.8;
- }
- break;
- case 3: /* specularColor */
- this_mat[15] = accept_float();
- this_mat[16] = accept_float();
- this_mat[17] = accept_float();
- if (read_ch('~') == 0) {
- this_mat[15] = 0.0;
- this_mat[16] = 0.0;
- this_mat[17] = 0.0;
- }
- break;
- case 4: /* emissiveColor */
- ecnt = 0;
- if (read_ch('[')) {
- this_mat[11] = accept_float();
- this_mat[12] = accept_float();
- this_mat[13] = accept_float();
- if (read_ch('~') == 0) {
- this_mat[11] = 0.0;
- this_mat[12] = 0.0;
- this_mat[13] = 0.0;
- }
- } else {
- while (read_ch(']')) {
- this_emis[ecnt][0] = accept_float();
- this_emis[ecnt][1] = accept_float();
- this_emis[ecnt][2] = accept_float();
- read_ch(',');
- ecnt++;
- if (ecnt == MAXEMIS) {
- errormsg("too many emissive values");
- }
- }
- this_mat[11] = this_emis[0][0];
- this_mat[12] = this_emis[0][1];
- this_mat[13] = this_emis[0][2];
- }
- break;
- case 5: /* shininess */
- this_mat[19] = accept_float();
- if (read_ch('~') == 0) {
- this_mat[19] = 0.0;
- }
- break;
- case 6: /* transparency */
- this_mat[1] = accept_float();
- if (read_ch('~') == 0) {
- this_mat[1] = 0.0;
- }
- break;
- case 7: /* vector */
- vcnt = 0;
- if (read_ch('[')) {
- this_vec[vcnt][0] = accept_float();
- this_vec[vcnt][1] = accept_float();
- this_vec[vcnt][2] = accept_float();
-
- } else {
- while (read_ch(']')) {
- this_vec[vcnt][0] = accept_float();
- this_vec[vcnt][1] = accept_float();
- this_vec[vcnt][2] = accept_float();
- read_ch(',');
- vcnt++;
- if (vcnt == MAXELEM) {
- errormsg("too many elements in vector object");
- }
- }
- }
- break;
- case 8: /* coordIndex */
- expect_ch('[');
- ccnt = 0;
- while (read_ch(']')) {
- this_cin[ccnt] = accept_int();
- read_ch(',');
- ccnt++;
- if (ccnt == MAXELEM) {
- errormsg("too many elements in coordindex");
- }
- }
- object_is_open = TRUE;
- break;
- case 9: /* normalIndex */
- expect_ch('[');
- ncnt = 0;
- while (read_ch(']')) {
- this_nin[ncnt] = accept_int();
- read_ch(',');
- ncnt++;
- if (ncnt == MAXELEM) {
- errormsg("too many elements in coordindex");
- }
- }
- break;
- case 10: /* point */
- expect_ch('[');
- pcnt = 0;
- while (read_ch(']')) {
- this_pnt[pcnt][0] = accept_float();
- this_pnt[pcnt][1] = accept_float();
- this_pnt[pcnt][2] = accept_float();
- read_ch(',');
- pcnt++;
- if (pcnt == MAXELEM) {
- errormsg("too many elements in point object");
- }
- }
- break;
- case 11: /* end */
- done = TRUE;
- /* run through */
- case 12: /* Separator */
- if (object_is_open) {
-
- if (ccnt != ncnt || (eicnt != 0 && eicnt != ccnt)) {
- errormsg("error in index count");
- }
- if (this_crease > 1.5) {
- smooth_normals(ncnt, this_vec, this_nin,
- this_cin);
- }
- mat = def_material(this_mat);
- objects[objcnt++] = build_object(mat, ccnt, this_vec, this_pnt,
- this_nin, this_cin, this_ein, this_emis, ecnt, backface_mode);
- object_is_open = FALSE;
- backface_mode = TRUE;
- eicnt = 0;
- ecnt = 0;
- this_crease = 2.0;
- }
- break;
- case 13: /* SURFACE */
- if (strstr(lookahead(), "SURFACE") != NULL) {
- backface_mode = FALSE;
- }
- break;
- case 14: /* translation */
- this_trans[0] = accept_float();
- this_trans[1] = accept_float();
- this_trans[2] = accept_float();
- break;
- case 15: /* axis */
- if (this_rot <= 2) {
- if (read_ch('X') == 0) {
- this_axis[this_rot] = 'X';
- } else if (read_ch('Y') == 0) {
- this_axis[this_rot] = 'Y';
- } else {
- expect_ch('Z');
- this_axis[this_rot] = 'Z';
- }
- }
- break;
- case 16: /* angle */
- if (this_rot <= 2) {
- this_angle[this_rot++] = accept_float();
- }
- break;
- case 17: /* scaleFactor */
- this_scale[0] = accept_float();
- this_scale[1] = accept_float();
- this_scale[2] = accept_float();
- break;
- case 18: /* creaseAngle */
- this_crease = accept_float();
- break;
- case 19: /* materialIndex */
- expect_ch('[');
- eicnt = 0;
- while (read_ch(']')) {
- this_ein[eicnt] = accept_int();
- read_ch(',');
- eicnt++;
- if (eicnt == MAXELEM) {
- errormsg("too many elements in materialindex");
- }
- }
- break;
- }
- } while (!done);
-
- /* now make all the objects in this file into one big object
- * by using callobj
- */
- makeobj(obj);
- if (this_scale[0] != 1 || this_scale[1] != 1 || this_scale[2] != 1) {
- scale(this_scale[0], this_scale[1], this_scale[2]);
- }
- if (this_angle[0] != 0) {
- rot(this_angle[0] / 3.141592 * 180, this_axis[0]);
- }
- if (this_angle[1] != 0) {
- rot(this_angle[1] / 3.141592 * 180, this_axis[1]);
- }
- if (this_angle[2] != 0) {
- rot(this_angle[2] / 3.141592 * 180, this_axis[2]);
- }
- if (this_trans[0] != 0 || this_trans[1] != 0 || this_trans[2] != 0) {
- translate(this_trans[0], this_trans[1], this_trans[2]);
- }
- for (j = 0; j < objcnt; j++) {
- callobj(objects[j]);
- }
- if (current_backmode != TRUE) {
- backface(TRUE);
- current_backmode = TRUE;
- }
- closeobj();
- hdestroy();
- close_file();
- }
-
-
- /*_________________________________________________________________________
- |
- | smooth_normals - add all normals together
- |
- | works (well, kind of works) by adding all normals together that belong
- | to some given point, and normalizing the result.
- |
- */
-
- void smooth_normals(int cnt, float vec[MAXELEM][3], int nin[MAXELEM],
- int cin[MAXELEM]) {
-
- float norml[MAXELEM][3];
- int i,k;
-
- for (i=0; i< cnt; i++) {
- norml[i][0] = 0.0;
- norml[i][1] = 0.0;
- norml[i][2] = 0.0;
- }
- for (i = 0; i< cnt; i++) {
- k = cin[i];
- /* if (k > cnt) errormsg("wrong k"); */
- if (k == -1) continue;
- vadd(norml[k], vec[nin[i]], norml[k]);
-
- }
- for (i=0; i< cnt; i++) {
- k = cin[i];
- /* if (k > cnt) errormsg("wrong k"); */
- if (k == -1) continue;
- vnormal2(norml[k], vec[cin[i]]);
- nin[i] = cin[i];
- }
- }
-
- /*_________________________________________________________________________
- |
- | matcmp - compare the materials
- |
- */
-
- int matcmp(const void *a, const void *b) {
- return memcmp(a, b, 21 * sizeof(float));
- }
-
-
- /*_________________________________________________________________________
- |
- | def_material - define a material
- |
- | if the material has been previously defined, then use that, otherwise
- | do a lmdef, and return the result
- |
- */
-
- int def_material(float *set_mat) {
- static float *materials = NULL;
- float *p;
- static unsigned int mat_cnt = 0;
- int cnt;
- int ret;
-
- if (materials == NULL) {
- materials = (float*)malloc(sizeof(float)*21);
- }
- cnt = mat_cnt;
- p = (float *)lsearch(set_mat, materials, &mat_cnt, 21*sizeof(float), matcmp);
- ret = (p - materials) / 21 +100;
- if (cnt != mat_cnt) {
- materials = (float*)realloc(materials, (mat_cnt+1) * sizeof(float)*21);
- lmdef(DEFMATERIAL, ret, 21, set_mat);
- }
- return ret;
-
- }
-
-
- /*_________________________________________________________________________
- |
- | sumcmp - function needed in lsearch, for comparing to ints
- |
- */
-
- int sumcmp(const void *a, const void *b) {
- return *((const int *)a) - *((const int *)b);
- }
-
-
- /*_________________________________________________________________________
- |
- | build_object - make a GL object from inventor data
- |
- | uses the data stored in the various vectors (filled by the read routine)
- | and make a gl object from it. If the very crude checksum is the same as
- | of a previousely created gl object, then re-use that object.
- | try to suppress unneeded calls (like calling n3f when the normal
- | vector didn't change at all.
- |
- */
-
- Object build_object(int mat, int num, float vec[MAXELEM][3],
- float punt[MAXELEM][3], int nin[MAXELEM], int cin[MAXELEM],
- int ein[MAXELEM], float emis[MAXEMIS][3], int ecnt, int backmode) {
-
- static int *checksums = NULL;
- static unsigned int check_cnt = 0;
- int cnt;
- unsigned int sum;
- int *p;
- int obj;
- int r1, r2, i, j, n, c, e, curremis, currnorm, qmsh;
- int Ob[2];
- r1 = -2; r2 = -2;
- sum = 0;
- currnorm = -2;
- curremis = -2;
- sum = (int ) (punt[0][0] + punt [1][2] + punt [0][1]) *1000;
- for (i=0; i< num * 3; i += 7) {
- j = *((int *)punt+i);
- sum = (sum ^ j )+ (j >> 4);
- }
- Ob[0] = sum;
- Ob[1] = 0;
- if ( checksums == NULL) {
- checksums = (int *)malloc(sizeof(int)*2);
- }
- cnt = check_cnt;
- p = (int *)lsearch(Ob, checksums, &check_cnt, 2 * sizeof(int), sumcmp);
- obj = (p - checksums) / 2 + 10000;
- if (cnt != check_cnt) {
- checksums = (int*)realloc(checksums,(check_cnt+1) * sizeof(int) * 2);
- makeobj(obj);
- if (last_mat_used != mat) {
- last_mat_used = mat;
- lmbind(MATERIAL, mat);
- }
- if (current_backmode != backmode) {
- backface(backmode);
- current_backmode = backmode;
- }
- if (ecnt != 0) {
- lmcolor(LMC_EMISSION);
- }
- i = 0;
- qmsh = 0;
- while (i < num) {
- if (cin[i+3] == -1) {
- /* it is a triangle */
- if (qmsh) {
- endqstrip();
- r1 = -2;
- r2 = -2;
- qmsh = 0;
- }
- bgntmesh();
- if (ecnt > 0) {
- e = ein[i];
- if (e != curremis) {
- RGBcolor((short)(emis[e][0] * 255),
- (short)(emis[e][1] * 255),
- (short)(emis[e][2] * 255));
- curremis = e;
- }
- }
- n = nin[i]; c = cin[i];
- if (n != currnorm) {
- n3f(vec[n]);
- currnorm = n;
- }
- v3f(punt[c]);
- i++;
- n = nin[i]; c = cin[i];
- if (ecnt > 0) {
- e = ein[i];
- if (e != curremis) {
- RGBcolor((short)(emis[e][0] * 255),
- (short)(emis[e][1] * 255),
- (short)(emis[e][2] * 255));
- curremis = e;
- }
- }
- if (n != currnorm) {
- n3f(vec[n]);
- currnorm = n;
- }
- v3f(punt[c]);
- i++;
- if (ecnt > 0) {
- e = ein[i];
- if (e != curremis) {
- RGBcolor((short)(emis[e][0] * 255),
- (short)(emis[e][1] * 255),
- (short)(emis[e][2] * 255));
- curremis = e;
- }
- }
- n = nin[i]; c = cin[i];
- if (n != currnorm) {
- n3f(vec[n]);
- currnorm = n;
- }
- v3f(punt[c]);
- i+=2;
- endtmesh();
- } else if (cin[i+4] == -1) {
- if (r1 != cin[i] || r2 != cin[i+1]) {
- if (qmsh)
- endqstrip();
- bgnqstrip();
- n = nin[i]; c = cin[i];
- if (n != currnorm) {
- n3f(vec[n]);
- currnorm = n;
- }
- v3f(punt[c]);
- i++;
- n = nin[i]; c = cin[i];
- if (n != currnorm) {
- n3f(vec[n]);
- currnorm = n;
- }
- v3f(punt[c]);
- i++;
- } else {
- i+=2;
- }
- n = nin[i+1]; c = cin[i+1];
- if (n != currnorm) {
- n3f(vec[n]);
- currnorm = n;
- }
- v3f(punt[c]);
- r1 = c;
- i++;
- n = nin[i-1]; c = cin[i-1];
- if (n != currnorm) {
- n3f(vec[n]);
- currnorm = n;
- }
- v3f(punt[c]);
- r2 = c;
- i+=2;
- qmsh = 1;
- } else {
- fprintf(stderr,"problems at i=%d\n", i);
- }
- }
- if (qmsh)
- endqstrip();
- if (ecnt > 0 )
- lmcolor(LMC_COLOR);
- closeobj();
- }
- return (Object) obj;
- }
-